/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package chelydra.sharelydra.client.network;

import chelydra.sharelydra.client.Core;
import chelydra.sharelydra.client.database.DatabaseManager;
import chelydra.sharelydra.client.file.FileManager;
import chelydra.sharelydra.client.friend.Notification;
import chelydra.sharelydra.client.message.DownloadPart;
import chelydra.sharelydra.client.message.UploadPart;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This thread take care of the file downloading.
 * It pre cut, download and write the files.
 * @author Benjamin
 */
public class DownloadFileThread extends Thread{

    int fileID;
    int size;
    InetAddress IPDestInet;
    String IPDest;
    int portDest;
    String fileName;
    
    public DownloadFileThread(int fileID, int size, String IPDest, int portDest, String fileName) throws UnknownHostException{
        this.size=size;
        this.fileID = fileID;
        this.portDest = portDest;
        this.IPDest = IPDest;
        this.IPDestInet = InetAddress.getByName(IPDest);
        this.fileName= fileName;
    }

    //the following example is done by cutting a string. It would be reeplace
    public void run(){
        int index=0; // index of the current position of the part of the file we change
        Socket s;
        try {
            s = new Socket(this.IPDestInet, this.portDest);
            OutputStream os = s.getOutputStream();
            InputStream is = s.getInputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String dataRecieved = "";
            System.out.println(" This Size "+this.size);
            System.out.println("index = "+ index+ "  Core.FilePArtMaxSize = "+Core.FilePartMaxSize);
            boolean notifSent=false;
            Core.getApplication().getView().updateDownloadTable(fileName, size, IPDest,"0");
            while( (index + Core.FilePartMaxSize ) < this.size ){
                int begin=0,end=0;
                begin = index;
                end = begin + Core.FilePartMaxSize;
                DownloadPart mes = new DownloadPart(this.fileID,begin,end);
                System.out.println("I request the part "+begin+ " to "+ end);
                osw.write(mes.toString(),0,mes.toString().length());
                osw.flush();
                index = 1 + end;
                String reply="";
                System.out.println("Download Thread is ready to recieve data");
                reply = br.readLine();
                UploadPart up = new UploadPart();
                up.fromString(reply);
                if(up.getStatus() == 0){
                    this.size = 0;
                    DatabaseManager dbm = Core.getApplication().getDatabaseManager();
                    Notification newNote = new Notification(Notification.FILE_DOWNLOAD_ERROR,this.fileName);
                    dbm.addNewNotification(newNote);
                    Core.getApplication().getView().updateNotifications();
                }
                if(notifSent == false && up.getStatus() != 0){
                    DatabaseManager dbm = Core.getApplication().getDatabaseManager();
                    Notification newNote = new Notification(Notification.FILE_DOWNLOADING_STARTED,this.fileName);
                    dbm.addNewNotification(newNote);
                    Core.getApplication().getView().updateNotifications();
                    notifSent = true;
                }
                System.out.println("I have received  an Upload Part");
                System.out.println("Begin from String");
                byte[] data = ByteConvertor.fromString(up.getFileData());
                System.out.println("End from String");
                System.out.println("The size of the data I recieved : " + data.length);
                FileManager.sliceWriter(fileName,begin, data);
                float progress = (float)((float)index/(float)size) * 100;
                Core.getApplication().getView().updateDownloadTable(fileName, size, IPDest,Float.toString(progress));
            }
            if(this.size != 0){
                int begin,end;
                begin = index;
                end = this.size;
                DownloadPart mes = new DownloadPart(this.fileID,begin,end);
                System.out.println("I request the part "+begin+ " to "+ end);
                osw.write(mes.toString(),0,mes.toString().length());
                osw.flush();
                index = index + Core.FilePartMaxSize + 1 ;
                String reply="";
                String temp = "";
                System.out.println("Download Thread is ready to recieve data");
                reply = br.readLine();
                UploadPart up = new UploadPart();
                up.fromString(reply);
                System.out.println("I have received an upload Part");
                byte[] data = ByteConvertor.fromString(up.getFileData());
                System.out.println("The size of the data I recieved : " + data.length);
                FileManager.sliceWriter(fileName,begin, data);
                System.out.println("Final file recieved");
                DatabaseManager dbm = Core.getApplication().getDatabaseManager();
                Notification newNote = new Notification(Notification.FILE_DOWNLOAD_FINISHED,this.fileName);
                dbm.addNewNotification(newNote);
                Core.getApplication().getView().emptyDownloadTable();
                Core.getApplication().getView().emptyTransferTable();
                Core.getApplication().getView().updateNotifications();
                osw.close();
            }
        } catch (IOException ex) {
            Logger.getLogger(DownloadFileThread.class.getName()).log(Level.SEVERE, null, ex);
        }
            


        
    }
    
}
